/* Copyright (C) 2016 RDA Technologies Limited and/or its affiliates("RDA").
* All rights reserved.
*
* This software is supplied "AS IS" without any warranties.
* RDA assumes no responsibility or liability for the use of the software,
* conveys no license or title under any patent, copyright, or mask work
* right to the product. RDA reserves the right to make changes in the
* software without notification.  RDA also make no representation or
* warranty that such application will be suitable for the specified use
* without further testing or modification.
*/




#ifndef _HAL_SIM_H_
#define _HAL_SIM_H_

#include "cs_types.h"

/// @defgroup sim HAL SIM Driver
/// This document describes the characteristics of the SIM module
/// and how to use it via its Hardware Abstraction Layer API.
///
/// @par Features
/// The SIM Card Interface automates the communication between the chip and the
/// SIM card and works with software drivers to interface with the SIM protocol
/// code :
/// - Even parity will be generated and checked for transmitted characters.
/// - Receive character count flag and interrupt.
/// - Automatic NULL character filtering.
/// - Programmable receive timeout.
/// - Programmable guard time and turnaround guard time.
/// - Automatic clock-stop for power saving.
/// - The SIM interface supports both SIMs with active high resets as well
/// as SIMs with active low resets.
/// - DMA capabilities to allow fully automated data transfer.
/// .
///
/// @par Automatic Reset
/// The SIM interface features an automatic reset sequence generator. If the
/// ATR is detected by the SIM interface, a reset detect flag is set and an
/// interrupt will be generated if the ATR interrupt is enabled. If the card
/// does not respond with the ATR within the timeout specified in the SIM
/// specification, the reset detect flag is not set, and an ATR interrupt is
/// generated if enabled. During the ATR, format and encoding/decoding are
/// automatically detected.
///
/// @par Transmission/Reception
/// To send or receive bytes to or from the SIM, two methods can be used
/// according to the quantity of data to transmit: direct or through DMA. The
/// driver function takes care of that transparently, and thus this is not a
/// concern for upper layer software.
///
///
///
///
/// @par Interruption Cause
/// Different interruption can be generated by this module. They are sent
/// to the user defined interrupt handler through a structure of type
/// #HAL_SIM_IRQ_STATUS_T. The user handler is registered by a call
/// to the module function #hal_SimIrqSetHandler.
///
/// @{


// ============================================================================
// TYPES
// ============================================================================


// ============================================================================
// HAL_SIM_CLOCK_STOP_MODE_T
// ----------------------------------------------------------------------------
/// This type is used to set the clock stop mode.
// ============================================================================
typedef enum
{
    /// Continuous clock mode, the autostop is disabled
    HAL_SIM_CLOCK_NO_STOP = 0,
    /// Automatic clock stop mode, stopped at low-level
    HAL_SIM_CLOCK_STOP_L = 1,
    /// Automatic clock stop mode, stopped at high-level
    HAL_SIM_CLOCK_STOP_H =2
} HAL_SIM_CLOCK_STOP_MODE_T;



// ============================================================================
// HAL_SIM_IRQ_STATUS_T
// ----------------------------------------------------------------------------
/// This type defines the interrupt causes offered by the SIM driver.
/// Please see below for details.
// ============================================================================
typedef struct
{
    /// When the reset time-outs.
    UINT32 resetTimeout:1;

    /// When a parity error occurs.
    UINT32 parityError:1;

    /// When a bad ts character is received.
    UINT32 badTs:1;

    /// When the auto-reset is successful.
    UINT32 atrSuccess:1;

    /// When a DMA tranfer has been finished
    UINT32 dmaSuccess:1;

    /// When an auto-reset has been started.
    UINT32 atrStart:1;

    /// When a work waiting time factor time-outs.
    UINT32 wwtTimeout:1;

    /// When the number of received character exceeds the
    /// number of awaited bytes:1; (set in the SCI Rx counter register)
    UINT32 extraRx:1;

} HAL_SIM_IRQ_STATUS_T;



// ============================================================================
// HAL_SIM_IRQ_HANDLER_T
// ----------------------------------------------------------------------------
/// Type of the user handler function. It is used to register the user handler
/// called when the SIM module generates an interrupt thanks to the function
/// hal_SimIrqSetHandler.
// ============================================================================
typedef  VOID (*HAL_SIM_IRQ_HANDLER_T)(HAL_SIM_IRQ_STATUS_T);




// ============================================================================
// FUNCTIONS
// ============================================================================

// ============================================================================
// hal_SimOpen
// ----------------------------------------------------------------------------
/// This function opens the SIM module drivers and enables the use of its API,
/// and initializes the SIM.
// ============================================================================
PUBLIC VOID hal_SimOpen(VOID);



// ============================================================================
// hal_SimClose
// ----------------------------------------------------------------------------
/// This function closes the SIM module drivers and forbids the use of its API.
/// #hal_SimPowerDown has been called before that function.
// ============================================================================
PUBLIC VOID hal_SimClose(VOID);



// ============================================================================
// hal_SimSetSimIndex
// ----------------------------------------------------------------------------
/// Set current SIM index.
/// @param index The SIM card interface index.
// ============================================================================
PUBLIC VOID hal_SimSetSimIndex(UINT8 index);



// ============================================================================
// hal_SimGetSimIndex
// ----------------------------------------------------------------------------
/// Get current SIM index.
/// @return current SIM index.
// ============================================================================
PUBLIC UINT8 hal_SimGetSimIndex(VOID);



// ============================================================================
// hal_SimEnableSciEx
// ----------------------------------------------------------------------------
/// Enalbe the specified SIM card interface hardware module.
/// @param index The SIM card interface index.
// ============================================================================
PUBLIC VOID hal_SimEnableSciEx(UINT8 index);



// ============================================================================
// hal_SimDisableSciEx
// ----------------------------------------------------------------------------
/// Disable the specified SIM card interface hardware module.
/// @param index The SIM card interface index.
// ============================================================================
PUBLIC VOID hal_SimDisableSciEx(UINT8 index);



// ============================================================================
// hal_SimEnableSci
// ----------------------------------------------------------------------------
/// Enalbe the SIM card interface hardware module.
// ============================================================================
PUBLIC VOID hal_SimEnableSci(VOID);



// ============================================================================
// hal_SimDisableSci
// ----------------------------------------------------------------------------
/// Disable the SIM card interface hardware module.
// ============================================================================
PUBLIC VOID hal_SimDisableSci(VOID);



// ============================================================================
// hal_SimClockStart
// ----------------------------------------------------------------------------
/// Start the clock sent to the SIM card.
///
/// This function requests a resource of #HAL_SYS_FREQ_26M.
/// The Resource is automatically released to #HAL_SYS_FREQ_32K when the sim allows it.
// ============================================================================
PUBLIC VOID hal_SimClockStart(VOID);



// ============================================================================
// hal_SimGetNumRxBytes
// ----------------------------------------------------------------------------
/// That function lets us know the number of bytes received from the SIM.
/// @return The number of bytes read from the SIM
// ============================================================================
PUBLIC UINT16 hal_SimGetNumRxBytes(VOID);



// ============================================================================
// hal_SimReset
// ----------------------------------------------------------------------------
/// This function starts the reset sequence, during which
/// the timing of each signal clock, data, vcc are directly controlled by
/// the driver. At the end of the reset, an ATR success interrupt
/// is sent
///
/// @param pRxByte Pointer to the buffer used to store the reset
/// command response
// ============================================================================
PUBLIC VOID hal_SimReset(UINT8* pRxByte, U8 length);



// ============================================================================
// hal_SimPowerDown
// ----------------------------------------------------------------------------
/// This function does a power down of the SIM. The timings of each signals
/// are controlled by the driver, which switch off the clock and Vcc.
// ============================================================================
PUBLIC VOID hal_SimPowerDown(VOID);



// ============================================================================
// hal_SimSetClockStopMode
// ----------------------------------------------------------------------------
/// This function is used to indicate to the driver how the sim clock should be
/// switch off, depending on the ATR response.
///
/// @param mode This is the stop mode to be set.
// ============================================================================
PUBLIC VOID hal_SimSetClockStopMode(HAL_SIM_CLOCK_STOP_MODE_T mode);



// ============================================================================
// hal_SimSetWorkWaitingTime
// ----------------------------------------------------------------------------
/// Set the work waiting time.
/// A timeout will be generated when the WWT is exceeded.  The WWT is calculated
/// by:
/// <code> WWT = 960 x WI x (F/Fi) </code>,
/// where Fi is the main SCI clock frequency (3-5 MHz) and F is 372 before an
/// enhanced PPS and 512 after an enhanced PPS. \n
/// The SCI_WI value must be calculated as follows:
/// <code> SCI_WI = WI * D </code>
/// Thus, by default (WI = 10) this value needs to be set to 10 before an EPPS,
/// but needs to be scaled to WI*D=80 after the EPPS procedure.
///
/// The hal driver is in charge of checking the time between each received sim
/// character. The default value (10) is not initialised by HAL.
///
/// @param wi WI factor used to set the WWT according to the previous formula.
// ============================================================================
PUBLIC VOID hal_SimSetWorkWaitingTime(UINT8 wi);



// ============================================================================
// hal_SimSetEtuDuration
// ----------------------------------------------------------------------------
/// Select the clock rate.
/// @param etuDuration F param to set.
/// @param etuDuration D param to set.
// ============================================================================
PUBLIC VOID hal_SimSetEtuDuration(UINT16 F, UINT8 D, UINT8 SciInvFlag);

// ============================================================================
// hal_SimDelayAfterEpps
// ----------------------------------------------------------------------------
/// Delay after EPPS procedure required for some SIM cards
// ============================================================================
PUBLIC VOID hal_SimDelayAfterEpps(VOID);


// ============================================================================
// hal_SimTxByteRxByte
// ----------------------------------------------------------------------------
/// Starts a SIM transfer.
/// A sim transfer consists in sending nTxByte and receiving an answer of
/// nRxByte.
/// At the end of the transfer, an interrupt is sent, which is recognized
/// by the user handler as "DMA success".
///
/// This function requests a resource of #HAL_SYS_FREQ_26M.
/// The Resource is automatically released to #HAL_SYS_FREQ_32K when the sim allows it.
///
/// @param nTxByte Number of byte to send (Size of the command)
/// @param pTxByte Pointer to the buffer containing the command to send
/// @param nRxByte Number of byte to receive (Size of the answer)
/// @param pRxByte Pointer to the buffer where to store the answer
/// @param stopClock In case of an operation consisting in two commands,
/// we do not want to stop the sim clock between the two commands. In that
/// case we set this parameter to \c FALSE for the first command.
/// Setting it to \c TRUE will stop the clock after the command (For the
/// second command of the pair or a standalone command).
// ============================================================================
PUBLIC VOID hal_SimTxByteRxByte(UINT16 nTxByte, CONST UINT8* pTxByte, UINT16 nRxByte,
                                UINT8* pRxByte, BOOL stopClock);



// ============================================================================
// hal_SimIrqSetHandler
// ----------------------------------------------------------------------------
/// Set the user function called when an interrupt is generated by the SIM
/// driver.
/// @param handler Handler function to set.
// ============================================================================
PUBLIC void hal_SimIrqSetHandler(HAL_SIM_IRQ_HANDLER_T handler);



// ============================================================================
// hal_SimIrqSetMask
// ----------------------------------------------------------------------------
/// Set the mask for the interruption. A '1' in a field of the structure means
/// an interruption must be triggered in the case if the corresponding
/// condition occurs (cf the type details for more information).
///
/// @param mask Mask to set.
// ============================================================================
PUBLIC VOID hal_SimIrqSetMask(HAL_SIM_IRQ_STATUS_T mask);



// ============================================================================
// hal_SimIrqGetMask
// ----------------------------------------------------------------------------
/// Get the IRQ mask for the SIM driver.
/// @return The Sim mask
// ============================================================================
PUBLIC HAL_SIM_IRQ_STATUS_T hal_SimIrqGetMask(VOID);

// ============================================================================
// hal_SimDMAReleaseIFC
// ----------------------------------------------------------------------------
/// release IFC when dma in progress
// ============================================================================
PUBLIC VOID hal_SimDMAReleaseIFC(VOID);
PUBLIC VOID hal_SimRegReset(VOID);
PUBLIC VOID hal_SimDeactive(u8 type);

// ============================================================================
// hal_SimInterfaceActive
// ----------------------------------------------------------------------------
/// This is used to determine when the interface is no longer busy.  It does
/// that by checking whether the SCI clock is off.  If it is off, the interface
/// has completed its current transaction including the shutdown delay.
/// @return TRUE if the interface is active and the clock is still on, FALSE
/// if the interface is inactive and the clock is off.
// ============================================================================
PUBLIC BOOL hal_SimInterfaceActive(VOID);

// ============================================================================
// hal_SimGetClkStatus
// ----------------------------------------------------------------------------
/// Returns the status of the clock:
/// @return 0 = clock on. \n
/// 1 = clock off
// ============================================================================
PUBLIC BOOL hal_SimGetClkStatus(VOID);

// ============================================================================
// hal_SimGetClkStopStatus
// ----------------------------------------------------------------------------
/// Returns the status of the clock stop mode:
/// @return 0 = manual mode. \n
/// 1 = auto stop mode
// ============================================================================
PUBLIC BOOL hal_SimGetClkStopStatus(VOID);

// ============================================================================
// hal_SimGetResetStatus
// ----------------------------------------------------------------------------
/// Returns the status of the reset pin after automatic reset procedure.  Since
/// the card is _not_ in reset after a successful ATR, the reset pin (and the
/// status bit) is in the _NON-ACTIVE RESET_ state.
/// @return 0 = Reset pin at 0 when not in reset (Active high Reset) \n
/// 1 = Reset pin at 1 when not in reset (Active low Reset)
// ============================================================================
PUBLIC UINT8 hal_SimGetResetStatus(VOID);

// ============================================================================
// hal_Switch2Manual
// ----------------------------------------------------------------------------
/// This function should be called after a successful ATR ONLY when using the
/// ARG.  After an ARG, the LLI and MSBH_LSBL control lines are internally
/// driven by the ARG state machine.  When in Dual SIM mode, the state machine
/// is restarted so the internal signals can no longer be used.  This function
/// parses the Ts value and switches to manual control for the format params.
/// This should only be necessary for Dual SIM drivers.
/// @param Ts is the Ts byte that is read and which will be used to determine
/// the transfer format.
// ============================================================================
PUBLIC UINT32 hal_SimSwitch2Manual(UINT8 Ts);

PUBLIC VOID hal_SimSetDataConvFormat(UINT32 Ts);

#ifdef GALLITE_IS_8806
PUBLIC VOID hal_SimSetDbg(VOID);

PUBLIC VOID hal_SimResetSys(VOID);
#endif


// FIXME: The three following functions should not be useful.
// ============================================================================
// hal_SimSetConfig
// ----------------------------------------------------------------------------
/// Set the config for the SIM driver.
/// @return The Sim config
// ============================================================================
PUBLIC VOID hal_SimSetConfig(VOID);
PUBLIC VOID hal_SimSetConfInvTS(VOID);
PUBLIC BOOL hal_SimArgStatus(VOID);



// ============================================================================
// hal_SimGetRegxxx
// ----------------------------------------------------------------------------
/// Get the register value for saving status.  Probably could encapsulate this
/// better but just do it like this for testing.
/// @return the corresponding register value
// ============================================================================
PUBLIC UINT32 hal_SimGetRegConfig(VOID);
PUBLIC UINT32 hal_SimGetRegClkDiv(VOID);
PUBLIC UINT32 hal_SimGetRegTimes(VOID);
PUBLIC UINT32 hal_SimGetRegChFilt(VOID);
PUBLIC UINT32 hal_SimGetRegIntMask(VOID);
PUBLIC VOID hal_simParseReg(VOID);

PUBLIC VOID hal_SimRestoreRegConfig(UINT32 Restore);
PUBLIC VOID hal_SimRestoreRegClkDiv(UINT32 Restore);
PUBLIC VOID hal_SimRestoreRegTimes(UINT32 Restore);
PUBLIC VOID hal_SimRestoreRegChFilt(UINT32 Restore);
PUBLIC VOID hal_SimRestoreRegIntMask(UINT32 Restore);


///  @} <- End of the Sim group
#endif  //  _HAL_SIM_H_


